package com.ease.actionscript.mapping.mapper;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import xjavadoc.XClass;

import com.ease.actionscript.Dynamic;

public abstract class AbstractActionScriptClassMapper extends AbstractActionScriptTypeMapper {

	protected Set<String> importClassNames;

	protected List<String> importClassNameList;

	protected boolean finalClass = false;

	protected boolean abstractClass = false;

	protected boolean dynamicClass = false;

	protected Class<?> clazz;

	protected XClass xclass;

	protected Class<?> superclass;

	protected Set<String> interfaceNames;

	protected List<Method> classMethods;

	protected List<Field> staticFields;

	protected List<Field> memberFields;

	public void prepare() {
		// if (isCompliant()) {
		/** */
		actionScriptMappingContext.addIncludeClass(clazz, this.projectName);
		// }

		if (null != clazz) {
			if (Modifier.isFinal(clazz.getModifiers())) {
				finalClass = true;
			}
			if (Modifier.isAbstract(clazz.getModifiers())) {
				abstractClass = true;
			}
			if (clazz.isAnnotationPresent(Dynamic.class)) {
				dynamicClass = true;
			}

		}
		if (null != clazz) {
			// destinationPath = actionScriptMappingContext.getDestinationSourceFolder() + "/" +
			// clazz.getPackage().getName().replace(".", "/");
			String destinationProjectName = buildDestinationProjectName(projectName);

			destinationPath = actionScriptMappingContext.getFlexWorkspacePath() + "/" + destinationProjectName + "/src/" + clazz.getPackage().getName().replace(".", "/");
			destinationFileName = clazz.getSimpleName() + ".as";
		}
	}

	public boolean isCompliant() {
		if (null != clazz && !isRemotingMapped(clazz)) {
			return false;
		}

		return true;
	}

	protected void optimize() {
		classMethods = escapeEmpty(classMethods);
		if (null != classMethods) {
			// sort
		}
		importClassNames = escapeEmpty(importClassNames);
		if (null != importClassNames) {
			this.importClassNameList = new ArrayList<String>(importClassNames);
			Collections.sort(importClassNameList);
		}
		// interfaceNames = escapeEmpty(interfaceNames);
		// if(null!=interfaceNames) {
		// Collections.sort(interfaceNames);
		// }
	}

	protected void addInterfaceName(String interfaceName) {
		if (null == interfaceNames) {
			interfaceNames = new HashSet<String>();
		}
		interfaceNames.add(interfaceName);
	}

	protected void addStaticField(Field staticField) {
		if (null == staticFields) {
			staticFields = new ArrayList<Field>();
		}
		staticFields.add(staticField);
	}

	protected void addMemberField(Field memberField) {
		if (null == memberFields) {
			memberFields = new ArrayList<Field>();
		}
		memberFields.add(memberField);
	}

	protected void addImportClassName(String importClassName) {
		if (null == importClassNames) {
			importClassNames = new HashSet<String>();
		}
		if (null != importClassName && importClassName.indexOf('.') > 0) {
			importClassNames.add(importClassName);
		}
	}

	protected void addClassMethod(Method classMethod) {
		if (null == classMethods) {
			classMethods = new ArrayList<Method>();
		}
		classMethods.add(classMethod);
	}

	/**
	 * @return the importClassNames
	 */
	public Set<String> getImportClassNames() {
		return importClassNames;
	}

	/**
	 * @param importClassNames
	 *            the importClassNames to set
	 */
	public void setImportClassNames(Set<String> importClassNames) {
		this.importClassNames = importClassNames;
	}

	/**
	 * @return the clazz
	 */
	public Class<?> getClazz() {
		return clazz;
	}

	/**
	 * @param clazz
	 *            the clazz to set
	 */
	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}

	/**
	 * @return the superclass
	 */
	public Class<?> getSuperclass() {
		return superclass;
	}

	/**
	 * @param superclass
	 *            the superclass to set
	 */
	public void setSuperclass(Class<?> superclass) {
		this.superclass = superclass;
	}

	/**
	 * @return the classMethods
	 */
	public List<Method> getClassMethods() {
		return classMethods;
	}

	/**
	 * @param classMethods
	 *            the classMethods to set
	 */
	public void setClassMethods(List<Method> classMethods) {
		this.classMethods = classMethods;
	}

	/**
	 * @return the finalClass
	 */
	public boolean isFinalClass() {
		return finalClass;
	}

	/**
	 * @param finalClass
	 *            the finalClass to set
	 */
	public void setFinalClass(boolean finalClass) {
		this.finalClass = finalClass;
	}

	/**
	 * @return the dynamicClass
	 */
	public boolean isDynamicClass() {
		return dynamicClass;
	}

	/**
	 * @param dynamicClass
	 *            the dynamicClass to set
	 */
	public void setDynamicClass(boolean dynamicClass) {
		this.dynamicClass = dynamicClass;
	}

	/**
	 * @return the interfaceNames
	 */
	public Set<String> getInterfaceNames() {
		return interfaceNames;
	}

	/**
	 * @param interfaceNames
	 *            the interfaceNames to set
	 */
	public void setInterfaceNames(Set<String> interfaceNames) {
		this.interfaceNames = interfaceNames;
	}

	/**
	 * @return the staticFields
	 */
	public List<Field> getStaticFields() {
		return staticFields;
	}

	/**
	 * @param staticFields
	 *            the staticFields to set
	 */
	public void setStaticFields(List<Field> staticFields) {
		this.staticFields = staticFields;
	}

	/**
	 * @return the memberFields
	 */
	public List<Field> getMemberFields() {
		return memberFields;
	}

	/**
	 * @param memberFields
	 *            the memberFields to set
	 */
	public void setMemberFields(List<Field> memberFields) {
		this.memberFields = memberFields;
	}

	/**
	 * @return the importClassNameList
	 */
	public List<String> getImportClassNameList() {
		return importClassNameList;
	}

	/**
	 * @param importClassNameList
	 *            the importClassNameList to set
	 */
	public void setImportClassNameList(List<String> importClassNameList) {
		this.importClassNameList = importClassNameList;
	}

	/**
	 * @return the xclass
	 */
	public XClass getXclass() {
		return xclass;
	}

	/**
	 * @param xclass
	 *            the xclass to set
	 */
	public void setXclass(XClass xclass) {
		this.xclass = xclass;
	}

	/**
	 * @return the abstractClass
	 */
	public boolean isAbstractClass() {
		return abstractClass;
	}

	/**
	 * @param abstractClass
	 *            the abstractClass to set
	 */
	public void setAbstractClass(boolean abstractClass) {
		this.abstractClass = abstractClass;
	}

}
